package com.zqs.controller;

import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.zqs.bean.ExamDO;
import com.zqs.bean.ScoreDO;
import com.zqs.bean.StudentDO;
import com.zqs.common.CustomException;
import com.zqs.common.R;
import com.zqs.common.RUtil;
import com.zqs.controller.vo.ExamAddBatchParam;
import com.zqs.controller.vo.ExamAddParam;
import com.zqs.controller.vo.ExamPageParam;
import com.zqs.mapper.ClasscMapper;
import com.zqs.mapper.ExamMapper;
import com.zqs.mapper.ScoreMapper;
import com.zqs.mapper.StudentMapper;
import lombok.AllArgsConstructor;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 考试管理
 *
 * @author zhangqingshan
 * @date 2024/03/31
 */
@RestController
@AllArgsConstructor
@RequestMapping("/exam")
public class ExamController {
    final ExamMapper examMapper;
    final ClasscMapper classcMapper;
    final StudentMapper studentMapper;
    final ScoreMapper scoreMapper;

    @PostMapping("/add")
    @Transactional
    public R add(@RequestBody @Validated ExamAddParam vo) {
        ExamDO examDO = new ExamDO();
        examDO.setExamName(vo.getExamName());
        examDO.setExamDate(vo.getExamDate());
        examDO.setCreateDate(new Date());
        examDO.setIsDel(false);
        return RUtil.ok(examMapper.insert(examDO));
    }

    @DeleteMapping("/del/{examNum}")
    public R del(@PathVariable("examNum") Integer examNum) {
        ExamDO examDO = new ExamDO();
        examDO.setExamNum(examNum);
        examDO.setIsDel(true);
        return RUtil.ok(examMapper.updateById(examDO));
    }

    @PutMapping("/recoverDel/{examNum}")
    @Transactional
    public R recoverDel(@PathVariable("examNum") Integer examNum) throws CustomException {
        ExamDO examDO = examMapper.selectById(examNum);
        if (examDO == null) {
            throw new CustomException("考试编号不存在");
        }
        if (!examDO.getIsDel()) {
            throw new CustomException("该考试未被删除");
        }
        examDO.setIsDel(true);
        return RUtil.ok(examMapper.updateById(examDO));
    }


    @PostMapping("/edit")
    public R edit(@RequestBody ExamDO examVO) {
        if (null == examMapper.selectById(examVO.getExamNum())) {
            return RUtil.fail("考试编号不存在");
        }
        return RUtil.ok(examMapper.updateById(examVO));
    }

    @PostMapping("/page")
    public R page(@RequestBody ExamPageParam param) {
        return RUtil.ok(examMapper.selectPage(param.getPage(), Wrappers.lambdaQuery(ExamDO.class)
                .like(StringUtils.isNotBlank(param.getExamName()), ExamDO::getExamName, param.getExamName())
                .ge(param.getStartDate() != null, ExamDO::getExamDate, param.getStartDate())
                .lt(param.getEndDate() != null, ExamDO::getExamDate, param.getEndDate())
                .eq(param.getIsDel() != null, ExamDO::getIsDel, param.getIsDel())
                .orderByDesc(ExamDO::getExamDate)));
    }

    @PostMapping("/addBatch")
    @Transactional
    public R addBatch(@RequestBody @Validated ExamAddBatchParam param) throws CustomException {
        // 校验
        if (null == examMapper.selectById(param.getExamNum())) {
            throw new CustomException("考试编号查不到对应考试");
        }
        if (null == classcMapper.selectById(param.getClasscNum())) {
            throw new CustomException("班级编号查不到对应班级");
        }
        if (param.getStudents() == null || param.getStudents().size() == 0) {
            throw new CustomException("学生列表不能为空");
        }
        if (param.getStudents().size() != param.getStudents().stream().map(ExamAddBatchParam.ExamAddBatchStudent::getStuNum).collect(Collectors.toSet()).size()) {
            throw new CustomException("学生列表中存在重复的学生,请核对数据后重新导入");
        }

        // 获取学生
        Map<String, String> stuDataMap = param.getStudents().stream().collect(Collectors.toMap(ExamAddBatchParam.ExamAddBatchStudent::getStuNum, ExamAddBatchParam.ExamAddBatchStudent::getStuName));
        List<StudentDO> stuDOS = studentMapper.selectList(Wrappers.lambdaQuery(StudentDO.class).eq(StudentDO::getClassNum, param.getClasscNum()).in(StudentDO::getStuNum, stuDataMap.keySet()));
        Map<String, String> stuDOSMap = stuDOS.stream().collect(Collectors.toMap(StudentDO::getStuNum, StudentDO::getStuName));
        // 将数据库中不存在的学生保存
        for (Map.Entry<String, String> entry : stuDataMap.entrySet()) {
            if (stuDOSMap.containsKey(entry.getKey()) && !stuDOSMap.get(entry.getKey()).equals(entry.getValue())) {
                throw new CustomException("学生编号为" + entry.getKey() + "的学生姓名与数据库中不一致");
            } else if (!stuDOSMap.containsKey(entry.getKey())) {
                StudentDO studentDO = new StudentDO();
                studentDO.setClassNum(param.getClasscNum());
                studentDO.setStuNum(entry.getKey());
                studentDO.setStuName(entry.getValue());
                studentMapper.insert(studentDO);
            }
        }

        // 导入成绩
        param.getStudents().forEach(stu -> {
            stu.getScores().forEach(score -> {
                scoreMapper.insert(new ScoreDO(param.getExamNum(), stu.getStuNum(), score.getSubjectName(), score.getScore(), score.getSchRank(), score.getClassRank()));
            });
        });

        return RUtil.ok(null);
    }
}
